home *** CD-ROM | disk | FTP | other *** search
- /**************************************
- *
- * UDP chat sample
- * ©1991 Apple Computer, MacDTS
- *
- * Written by Steve Falkenburg 12/13/91
- *
- * this sample illustrates how to send and receive MacTCP UDP packets, setting up a simple
- * connectionless chat program. Instead of an outstanding read command, an ASR is
- * used to inform the program there is data to be received. This sample is written for
- * Think C 5.0, but can be converted easily to MPW C.
- *
- *************************************/
-
-
- #include <MacTCPCommonTypes.h>
- #include <AddressXlation.h>
- #include <UDPPB.h>
- #include <GetMyIPAddr.h>
-
- /* consts */
-
- #define kDlgID 128 // dialog item ids
- #define kSend 1
- #define kQuit 2
- #define kSendData 3
- #define kSendTo 4
- #define kRecvData 5
- #define kOutline 9
- #define kErrDlg 129
-
- #define kInFront (WindowPtr)-1L
-
- #define kUDPPort 12345
- #define kSenderPort 0
- #define kTimeout 5
-
- /* prototypes */
-
- void main(void);
- void InitStuff(void);
- void DoError(OSErr err);
- void MainLoop(void);
- OSErr DoSendData(DialogPtr theDlg);
- OSErr DoRecvData(DialogPtr theDlg);
-
- pascal void DNRResultProc(struct hostInfo *hInfoPtr,char *userDataPtr);
- OSErr ConvertStringToAddr(char *name,ip_addr *netNum);
-
- OSErr NetInitUDP(void);
- OSErr NetDoneUDP(void);
- OSErr NetSendUDP(StreamPtr sendStream,ip_addr sendAddr,udp_port sendPort,char *sendData);
- OSErr NetReadUDP(StreamPtr stream,Ptr data,unsigned short *dataLength);
- OSErr CreateUDPStream(udp_port udpPort,StreamPtr *theStream,ProcPtr asr);
- OSErr ReleaseUDPStream(StreamPtr theStream);
-
- pascal void MyASR(
- StreamPtr udpStream,
- unsigned short eventCode,
- Ptr userDataPtr,
- struct ICMPReport *icmpMsg);
- void DoASR(StreamPtr udpStream,unsigned short eventCode,struct ICMPReport *icmpMsg);
- OSErr GetMyIPAddr(ip_addr *addr);
- void NumToIPAddr(ip_addr addr,StringPtr ipStr);
-
- pascal void FrameItem(DialogPtr theDlg,short item);
-
-
- /* globals */
-
- static short gMTCPDrvr; // MacTCP Driver refnum
- StreamPtr gListenerStream; // udp listener stream
- StreamPtr gSenderStream; // udp sender stream
- Boolean gDataPending; // true if data has been received
- ip_addr gMyIPAddr; // my IP address
-
- void main(void)
- {
- OSErr err;
-
- InitStuff();
-
- if ((err=NetInitUDP())==noErr)
- MainLoop();
- else
- DoError(err);
-
- err = NetDoneUDP();
- if (err!=noErr)
- DoError(err);
-
- ExitToShell();
- }
-
-
- /* init the toolbox */
-
- void InitStuff(void)
- {
- InitGraf(&qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(nil);
- FlushEvents(everyEvent,0);
- InitCursor();
-
- gDataPending = false;
- }
-
-
- /* display an error */
-
- void DoError(OSErr err)
- {
- Str255 errStr;
-
- NumToString(err,errStr);
- ParamText(errStr,"\p","\p","\p");
- StopAlert(kErrDlg,nil);
- }
-
-
- /* main loop of execution */
-
- void MainLoop(void)
- {
- short item;
- DialogPtr theDlg;
- Handle iHndl;
- Rect iRect;
- short iType;
- OSErr err;
- Str255 ipStr;
-
- theDlg = GetNewDialog(kDlgID,nil,kInFront);
- GetDItem(theDlg,kOutline,&iType,&iHndl,&iRect);
- SetDItem(theDlg,kOutline,iType,FrameItem,&iRect);
- GetDItem(theDlg,kSendTo,&iType,&iHndl,&iRect);
- NumToIPAddr(gMyIPAddr,ipStr);
- SetIText(iHndl,ipStr);
- SelIText(theDlg,kSendData,0,32767);
-
- do {
- ModalDialog(nil,&item);
- if (item==kSend) {
- err = DoSendData(theDlg);
- if (err!=noErr)
- DoError(err);
- }
- if (gDataPending) {
- err = DoRecvData(theDlg);
- gDataPending = false;
- if (err!=noErr)
- DoError(err);
- }
-
- } while (item!=kQuit);
-
- DisposeDialog(theDlg);
- }
-
-
- /* called to initiate the sending of the UDP packet */
-
- OSErr DoSendData(DialogPtr theDlg)
- {
- Handle iHndl;
- Rect iRect;
- short iType;
- char sendTo[256],sendData[256];
- ip_addr sendAddr;
- OSErr err;
-
- GetDItem(theDlg,kSendTo,&iType,&iHndl,&iRect);
- GetIText(iHndl,(StringPtr)sendTo);
- GetDItem(theDlg,kSendData,&iType,&iHndl,&iRect);
- GetIText(iHndl,(StringPtr)sendData);
- PtoCstr(sendTo);
- PtoCstr(sendData);
-
- err = ConvertStringToAddr(sendTo,&sendAddr);
- if (err!=noErr)
- return err;
-
- err = NetSendUDP(gSenderStream,sendAddr,kUDPPort,sendData);
- return err;
- }
-
-
- /* called to initiate the receiving of a UDP packet */
-
- OSErr DoRecvData(DialogPtr theDlg)
- {
- OSErr err;
- char incoming[256];
- unsigned short dataLength;
- Handle iHndl;
- Rect iRect;
- short iType;
-
- dataLength = 255;
- err = NetReadUDP(gListenerStream,incoming,&dataLength);
- if (err!=noErr)
- return err;
-
- incoming[dataLength] = '\0';
- CtoPstr(incoming);
-
- GetDItem(theDlg,kRecvData,&iType,&iHndl,&iRect);
- SetIText(iHndl,(StringPtr)incoming);
-
- return noErr;
- }
-
-
- /* This is the completion routine used for name-resolver calls.
- It sets the userDataPtr flag to indicate the call has completed.
- */
-
- pascal void DNRResultProc(struct hostInfo *hInfoPtr,char *userDataPtr)
- {
- #pragma unused (hInfoPtr)
-
- *userDataPtr = 0xff;
- }
-
-
- /* ConvertStringToAddr is a simple call to get a host's IP number, given the name
- of the host. It copies the fully qualified name back into name, so make sure
- there's space.
- */
-
- OSErr ConvertStringToAddr(char *name,ip_addr *netNum)
- {
- struct hostInfo hInfo;
- OSErr result;
- char done = 0x00;
- extern Boolean gCancel;
-
- if ((result = OpenResolver(nil)) == noErr) {
- result = StrToAddr(name,&hInfo,DNRResultProc,&done);
- if (result == cacheFault)
- while (!done)
- ; /* wait for cache fault resolver to be called by interrupt */
- CloseResolver();
- if ((hInfo.rtnCode == noErr) || (hInfo.rtnCode == cacheFault)) {
- *netNum = hInfo.addr[0];
- strcpy(name,hInfo.cname);
- name[strlen(name)-1] = '\0';
- return noErr;
- }
- }
- *netNum = 0;
-
- return result;
- }
-
-
- /* initialize the MacTCP driver */
-
- OSErr NetInitUDP(void)
- {
- OSErr err;
-
- err = OpenDriver("\p.IPP",&gMTCPDrvr);
- if (err!=noErr)
- return err;
-
- err = CreateUDPStream(kUDPPort,&gListenerStream,MyASR);
- if (err!=noErr)
- return err;
-
- err = CreateUDPStream(kSenderPort,&gSenderStream,nil);
- if (err!=noErr)
- return err;
-
- err = GetMyIPAddr(&gMyIPAddr);
- return err;
- }
-
-
- OSErr NetDoneUDP(void)
- {
- OSErr err,err2;
-
- err = ReleaseUDPStream(gSenderStream);
- err2 = ReleaseUDPStream(gListenerStream);
-
- if (err==noErr)
- err = err2;
-
- return err;
- }
-
-
- /* release a UDP Stream */
-
- OSErr ReleaseUDPStream(StreamPtr theStream)
- {
- UDPiopb udpBlock;
- OSErr err;
-
- udpBlock.ioCRefNum = gMTCPDrvr;
- udpBlock.csCode = UDPRelease;
- udpBlock.udpStream = theStream;
- err = PBControl(&udpBlock,false);
- if (err!=noErr)
- return err;
-
- DisposPtr(udpBlock.csParam.create.rcvBuff);
- return MemError();
- }
-
-
-
- /* listen for incoming messages */
-
- OSErr CreateUDPStream(udp_port udpPort,StreamPtr *theStream,ProcPtr asr)
- {
- UDPiopb udpBlock;
- unsigned long bfrSize;
- Ptr buff;
- OSErr err;
-
- bfrSize = 2048;
- buff = NewPtr(bfrSize);
- if (MemError()!=noErr)
- return MemError();
-
- udpBlock.ioCRefNum = gMTCPDrvr;
- udpBlock.csCode = UDPCreate;
- udpBlock.csParam.create.rcvBuff = buff;
- udpBlock.csParam.create.rcvBuffLen = bfrSize;
- udpBlock.csParam.create.localPort = udpPort;
- udpBlock.csParam.create.notifyProc = asr;
- #ifdef __SYSEQU__
- udpBlock.csParam.create.userDataPtr = *(long *)CurrentA5;
- #else
- udpBlock.csParam.create.userDataPtr = CurrentA5;
- #endif
- err = PBControl(&udpBlock,false);
- if (err!=noErr)
- return err;
-
- *theStream = udpBlock.udpStream;
- }
-
-
- /* send an outgoing message */
-
- OSErr NetSendUDP(StreamPtr sendStream,ip_addr sendAddr,udp_port sendPort,char *sendData)
- {
- UDPiopb udpBlock;
- EventRecord ev;
- struct wdsEntry theWDS[2];
- OSErr err;
-
- theWDS[0].length = strlen(sendData);
- theWDS[0].ptr = sendData;
- theWDS[1].length = 0;
- theWDS[1].ptr = nil;
-
- udpBlock.udpStream = sendStream;
- udpBlock.ioCompletion = nil;
- udpBlock.ioCRefNum = gMTCPDrvr;
- udpBlock.csCode = UDPWrite;
- udpBlock.csParam.send.reserved = 0;
- udpBlock.csParam.send.remoteHost = sendAddr;
- udpBlock.csParam.send.remotePort = sendPort;
- udpBlock.csParam.send.checkSum = true;
- udpBlock.csParam.send.wdsPtr = (Ptr)theWDS;
- err = PBControl(&udpBlock,true);
- while (udpBlock.ioResult>0)
- EventAvail(everyEvent,&ev);
- return udpBlock.ioResult;
- }
-
-
- /* receive an incoming packet of data */
-
- OSErr NetReadUDP(StreamPtr stream,Ptr data,unsigned short *dataLength)
- {
- UDPiopb udpBlock;
- OSErr err;
-
- udpBlock.udpStream = stream;
- udpBlock.ioCRefNum = gMTCPDrvr;
- udpBlock.csCode = UDPRead;
- udpBlock.csParam.receive.timeOut = kTimeout;
- udpBlock.csParam.receive.secondTimeStamp = 0;
- err = PBControl(&udpBlock,false);
- if (err!=noErr)
- return err;
-
- if (udpBlock.csParam.receive.rcvBuffLen==0)
- return noErr;
-
- if (udpBlock.csParam.receive.rcvBuffLen < *dataLength)
- *dataLength = udpBlock.csParam.receive.rcvBuffLen;
-
- BlockMove(udpBlock.csParam.receive.rcvBuff,data,*dataLength);
-
- udpBlock.csCode = UDPBfrReturn;
- err = PBControl(&udpBlock,false);
- return err;
- }
-
-
-
- /* our async. notification routine */
-
- pascal void MyASR(
- StreamPtr udpStream,
- unsigned short eventCode,
- Ptr userDataPtr,
- struct ICMPReport *icmpMsg)
- {
- long oldA5;
-
- oldA5 = SetA5((long)userDataPtr);
- DoASR(udpStream,eventCode,icmpMsg);
- SetA5(oldA5);
- }
-
-
- void DoASR(StreamPtr udpStream,unsigned short eventCode,struct ICMPReport *icmpMsg)
- {
- if (eventCode==UDPDataArrival && udpStream==gListenerStream) {
- gDataPending = true;
- }
- }
-
-
- /* return the IP address for this machine */
-
- OSErr GetMyIPAddr(ip_addr *addr)
- {
- struct GetAddrParamBlock ipBlock; // may have to change this to IPParamBlock
- OSErr err;
-
- ipBlock.csCode = ipctlGetAddr;
- ipBlock.ioCRefNum = gMTCPDrvr;
- err = PBControl(&ipBlock,false);
- *addr = ipBlock.ourAddress;
-
- return err;
- }
-
-
- /*-------*/
-
- pascal void FrameItem(DialogPtr theDlg,short item)
- {
- Handle iHndl;
- Rect iRect;
- short iType;
-
- GetDItem(theDlg,item,&iType,&iHndl,&iRect);
- FrameRect(&iRect);
- }
-
-
- void NumToIPAddr(ip_addr addr,StringPtr ipStr)
- {
- sprintf(ipStr,"%lu.%lu.%lu.%lu",( addr >> 24),
- ((addr & 0x00FFFFFF) >> 16),((addr & 0x0000FFFF) >> 8),
- ( addr & 0x000000FF));
- CtoPstr(ipStr);
- }